import mongoose from 'mongoose';
import PermissionDAO from '../dao/PermissionDAO';
import RolePermissionDAO from '../dao/RolePermissionDAO';
import UserRoleDAO from '../dao/UserRoleDAO';
import { IPermission, IPermissionDocument } from '../models/permission';
import { IRolePermissionDocument } from '../models/rolePermission';
import { IUserRoleDocument } from '../models/userRole';

/**
 * 权限服务类
 * 提供权限管理相关的业务逻辑
 */
export class PermissionService {
  private permissionDAO: PermissionDAO;
  private rolePermissionDAO: RolePermissionDAO;
  private userRoleDAO: UserRoleDAO;

  constructor() {
    this.permissionDAO = new PermissionDAO();
    this.rolePermissionDAO = new RolePermissionDAO();
    this.userRoleDAO = new UserRoleDAO();
  }

  /**
   * 创建权限
   * @param permissionData 权限数据
   * @returns 创建的权限文档
   */
  async createPermission(permissionData: Partial<IPermission>): Promise<IPermissionDocument> {
    try {
      // 验证必填字段
      if (!permissionData.name || !permissionData.code || !permissionData.type) {
        throw new Error('Permission name, code, and type are required');
      }

      // 检查权限编码是否已存在
      const existingPermission = await this.permissionDAO.findByCode(permissionData.code);
      if (existingPermission) {
        throw new Error('Permission code already exists');
      }

      // 设置默认值
      const permission = {
        ...permissionData,
        sort: permissionData.sort || 0,
        status: permissionData.status !== undefined ? permissionData.status : 1,
        isSystem: permissionData.isSystem || false,
        dependencies: permissionData.dependencies || [],
        createdAt: new Date(),
        updatedAt: new Date()
      };

      return await this.permissionDAO.create(permission);
    } catch (error) {
      throw error;
    }
  }

  /**
   * 检查用户是否拥有指定权限
   * @param userId 用户ID
   * @param permissionCode 权限编码
   * @param systemId 系统ID（可选）
   * @returns 是否拥有权限
   */
  async checkPermission(
    userId: mongoose.Types.ObjectId | string,
    permissionCode: string,
    systemId?: mongoose.Types.ObjectId | string
  ): Promise<boolean> {
    try {
      if (!userId || !permissionCode) {
        throw new Error('User ID and permission code are required');
      }

      // 获取权限信息
      const permission = await this.permissionDAO.findByCode(permissionCode);
      if (!permission || permission.status !== 1) {
        return false;
      }

      // 如果指定了系统ID，检查权限是否属于该系统
      if (systemId && permission.systemId && !permission.systemId.equals(systemId as any)) {
        return false;
      }

      // 获取用户在指定系统中的角色
      const userRoles = await this.userRoleDAO.findByUserId(userId, systemId);
      if (!userRoles || userRoles.length === 0) {
        return false;
      }

      // 检查用户的角色是否拥有该权限
      for (const userRole of userRoles) {
        if (userRole.status === 1) { // 角色状态正常
          const hasPermission = await this.rolePermissionDAO.hasPermission(
            userRole.roleId as mongoose.Types.ObjectId,
            permission._id as mongoose.Types.ObjectId,
            systemId
          );
          if (hasPermission) {
            return true;
          }
        }
      }

      return false;
    } catch (error) {
      throw error;
    }
  }

  /**
   * 获取用户权限列表
   * @param userId 用户ID
   * @param systemId 系统ID（可选）
   * @returns 用户权限列表
   */
  async getUserPermissions(
    userId: mongoose.Types.ObjectId | string,
    systemId?: mongoose.Types.ObjectId | string
  ): Promise<IPermissionDocument[]> {
    try {
      if (!userId) {
        throw new Error('User ID is required');
      }

      // 获取用户在指定系统中的角色
      const userRoles = await this.userRoleDAO.findByUserId(userId, systemId);
      if (!userRoles || userRoles.length === 0) {
        return [];
      }

      const permissionIds = new Set<string>();

      // 收集所有角色的权限ID
      for (const userRole of userRoles) {
        if (userRole.status === 1) { // 角色状态正常
          const rolePermissions = await this.rolePermissionDAO.findByRoleId(
            userRole.roleId as mongoose.Types.ObjectId,
            systemId
          );
          
          rolePermissions.forEach(rp => {
            if (rp.status === 1) { // 权限分配状态正常
              permissionIds.add(rp.permissionId.toString());
            }
          });
        }
      }

      // 获取权限详情
      const permissions: IPermissionDocument[] = [];
      for (const permissionId of permissionIds) {
        const permission = await this.permissionDAO.findById(permissionId);
        if (permission && permission.status === 1) {
          permissions.push(permission);
        }
      }

      return permissions;
    } catch (error) {
      throw error;
    }
  }

  /**
   * 批量检查权限
   * @param userId 用户ID
   * @param permissionCodes 权限编码列表
   * @param systemId 系统ID（可选）
   * @returns 权限检查结果映射
   */
  async batchCheckPermissions(
    userId: mongoose.Types.ObjectId | string,
    permissionCodes: string[],
    systemId?: mongoose.Types.ObjectId | string
  ): Promise<{ [permissionCode: string]: boolean }> {
    try {
      if (!userId || !permissionCodes || permissionCodes.length === 0) {
        throw new Error('User ID and permission codes are required');
      }

      const result: { [permissionCode: string]: boolean } = {};

      // 批量检查权限
      for (const permissionCode of permissionCodes) {
        result[permissionCode] = await this.checkPermission(userId, permissionCode, systemId);
      }

      return result;
    } catch (error) {
      throw error;
    }
  }

  /**
   * 获取用户菜单权限
   * @param userId 用户ID
   * @param systemId 系统ID（可选）
   * @returns 菜单权限列表
   */
  async getUserMenuPermissions(
    userId: mongoose.Types.ObjectId | string,
    systemId?: mongoose.Types.ObjectId | string
  ): Promise<IPermissionDocument[]> {
    try {
      if (!userId) {
        throw new Error('User ID is required');
      }

      // 获取用户所有权限
      const allPermissions = await this.getUserPermissions(userId, systemId);

      // 过滤出页面和路由权限
      const menuPermissions = allPermissions.filter(permission => 
        permission.type === 'page' || permission.type === 'route'
      );

      // 按sort字段排序
      menuPermissions.sort((a, b) => a.sort - b.sort);

      return menuPermissions;
    } catch (error) {
      throw error;
    }
  }

  /**
   * 检查API权限
   * @param userId 用户ID
   * @param apiPath API路径
   * @param method HTTP方法
   * @param systemId 系统ID（可选）
   * @returns 是否拥有API权限
   */
  async checkApiPermission(
    userId: mongoose.Types.ObjectId | string,
    apiPath: string,
    method: string,
    systemId?: mongoose.Types.ObjectId | string
  ): Promise<boolean> {
    try {
      if (!userId || !apiPath || !method) {
        throw new Error('User ID, API path, and method are required');
      }

      // 查找对应的API权限
      const apiPermissions = await this.permissionDAO.findByType('api');
      const matchedPermission = apiPermissions.find(permission => 
        permission.apiPath === apiPath && 
        permission.method?.toLowerCase() === method.toLowerCase() &&
        permission.status === 1
      );

      if (!matchedPermission) {
        return false; // 没有找到对应的API权限配置
      }

      // 检查用户是否拥有该权限
      return await this.checkPermission(userId, matchedPermission.code, systemId);
    } catch (error) {
      throw error;
    }
  }

  /**
   * 更新权限
   * @param permissionId 权限ID
   * @param updateData 更新数据
   * @returns 更新后的权限文档
   */
  async updatePermission(
    permissionId: mongoose.Types.ObjectId | string,
    updateData: Partial<IPermission>
  ): Promise<IPermissionDocument | null> {
    try {
      if (!permissionId) {
        throw new Error('Permission ID is required');
      }

      // 检查权限是否存在
      const existingPermission = await this.permissionDAO.findById(permissionId);
      if (!existingPermission) {
        throw new Error('Permission not found');
      }

      // 系统权限不允许修改关键字段
      if (existingPermission.isSystem) {
        const restrictedFields = ['code', 'type', 'isSystem'];
        for (const field of restrictedFields) {
          if (updateData[field as keyof IPermission] !== undefined) {
            throw new Error(`Cannot modify ${field} of system permission`);
          }
        }
      }

      // 如果更新权限编码，检查是否重复
      if (updateData.code && updateData.code !== existingPermission.code) {
        const codeExists = await this.permissionDAO.findByCode(updateData.code);
        if (codeExists) {
          throw new Error('Permission code already exists');
        }
      }

      const updatedData = {
        ...updateData,
        updatedAt: new Date()
      };

      return await this.permissionDAO.update(permissionId, updatedData);
    } catch (error) {
      throw error;
    }
  }

  /**
   * 删除权限
   * @param permissionId 权限ID
   * @returns 是否删除成功
   */
  async deletePermission(permissionId: mongoose.Types.ObjectId | string): Promise<boolean> {
    try {
      if (!permissionId) {
        throw new Error('Permission ID is required');
      }

      // 检查权限是否存在
      const permission = await this.permissionDAO.findById(permissionId);
      if (!permission) {
        throw new Error('Permission not found');
      }

      // 系统权限不允许删除
      if (permission.isSystem) {
        throw new Error('Cannot delete system permission');
      }

      // 检查是否有角色使用该权限
      const rolePermissions = await this.rolePermissionDAO.findByPermissionId(permissionId);
      if (rolePermissions.length > 0) {
        throw new Error('Cannot delete permission that is assigned to roles');
      }

      return await this.permissionDAO.delete(permissionId);
    } catch (error) {
      throw error;
    }
  }

  /**
   * 获取权限详情
   * @param permissionId 权限ID
   * @returns 权限文档
   */
  async getPermissionById(permissionId: mongoose.Types.ObjectId | string): Promise<IPermissionDocument | null> {
    try {
      if (!permissionId) {
        throw new Error('Permission ID is required');
      }

      return await this.permissionDAO.findById(permissionId);
    } catch (error) {
      throw error;
    }
  }

  /**
   * 根据权限编码获取权限
   * @param code 权限编码
   * @returns 权限文档
   */
  async getPermissionByCode(code: string): Promise<IPermissionDocument | null> {
    try {
      if (!code) {
        throw new Error('Permission code is required');
      }

      return await this.permissionDAO.findByCode(code);
    } catch (error) {
      throw error;
    }
  }

  /**
   * 获取系统权限列表
   * @param systemId 系统ID（可选）
   * @returns 系统权限列表
   */
  async getSystemPermissions(systemId?: mongoose.Types.ObjectId | string): Promise<IPermissionDocument[]> {
    try {
      if (systemId) {
        return await this.permissionDAO.findBySystemId(systemId);
      } else {
        return await this.permissionDAO.getSystemPermissions();
      }
    } catch (error) {
      throw error;
    }
  }

  /**
   * 构建权限树
   * @param systemId 系统ID（可选）
   * @returns 权限树结构
   */
  async buildPermissionTree(systemId?: mongoose.Types.ObjectId | string): Promise<any[]> {
    try {
      return await this.permissionDAO.buildPermissionTree(systemId);
    } catch (error) {
      throw error;
    }
  }
}

export default PermissionService;